/*
 *  Copyright (C) 2005-2007 Renier Roth
 *  www.renier.de
 *
 *  This program is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU General Public License
 *  as published by the Free Software Foundation; either version 2
 *  of the License, or any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */
package de.renier.jkeepass;

import java.awt.BorderLayout;
import java.awt.ComponentOrientation;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Point;
import java.awt.event.ActionEvent;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.table.TableCellRenderer;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreePath;

import de.renier.jkeepass.actions.ActionManager;
import de.renier.jkeepass.actions.EditBasicElementAction;
import de.renier.jkeepass.components.BasicElementTable;
import de.renier.jkeepass.components.SymbolComboBox;
import de.renier.jkeepass.elements.BasicElement;
import de.renier.jkeepass.elements.ContainerElement;
import de.renier.jkeepass.elements.Element;
import de.renier.jkeepass.model.BasicElementTableModel;
import de.renier.jkeepass.renderer.JLabelTableRenderer;
import de.renier.jkeepass.renderer.PasswordTableCellRenderer;
import de.renier.jkeepass.util.Utils;

/**
 * ContainerElementPanel
 *
 * @author <a href="mailto:software@renier.de">Renier Roth</a>
 */
public class ContainerElementPanel extends JPanel implements TreeSelectionListener {

  private static final long serialVersionUID = 1L;
  private JPanel jPanel = null;
  private JScrollPane jScrollPane = null;
  private JTable jTable = null;
  private JLabel nameLabel = null;
  private JTextField nameTextField = null;
  private ContainerElement containerElement;  //  @jve:decl-index=0:
  private JButton submitButton = null;
  private JComboBox symbolComboBox = null;
  private JPopupMenu jPopupMenu = null;
  private EditBasicElementAction editBasicElementAction = new EditBasicElementAction(null);  //  @jve:decl-index=0:

  /**
   * This is the default constructor
   */
  public ContainerElementPanel() {
    super();
    initialize();
  }

  /**
   * This method initializes this
   * 
   * @return void
   */
  private void initialize() {
    this.setSize(300, 200);
    this.setLayout(new BorderLayout());
    this.add(getJPanel(), BorderLayout.NORTH);
    this.add(getJScrollPane(), BorderLayout.CENTER);
    editBasicElementAction.setEnabled(false);
  }

  /**
   * This method initializes jPanel	
   * 	
   * @return javax.swing.JPanel	
   */
  private JPanel getJPanel() {
    if (jPanel == null) {
      GridBagConstraints gridBagConstraints11 = new GridBagConstraints();
      gridBagConstraints11.fill = GridBagConstraints.NONE;
      gridBagConstraints11.gridy = 0;
      gridBagConstraints11.weightx = 1.0;
      gridBagConstraints11.insets = new Insets(10, 10, 0, 10);
      gridBagConstraints11.anchor = GridBagConstraints.WEST;
      gridBagConstraints11.gridx = 2;
      GridBagConstraints gridBagConstraints2 = new GridBagConstraints();
      gridBagConstraints2.gridx = 0;
      gridBagConstraints2.gridwidth = 3;
      gridBagConstraints2.insets = new Insets(5, 10, 5, 10);
      gridBagConstraints2.gridy = 1;
      GridBagConstraints gridBagConstraints1 = new GridBagConstraints();
      gridBagConstraints1.insets = new Insets(10, 10, 0, 0);
      gridBagConstraints1.gridy = 0;
      gridBagConstraints1.gridx = 0;
      GridBagConstraints gridBagConstraints = new GridBagConstraints();
      gridBagConstraints.fill = GridBagConstraints.HORIZONTAL;
      gridBagConstraints.gridy = 0;
      gridBagConstraints.weightx = 1.0;
      gridBagConstraints.anchor = GridBagConstraints.WEST;
      gridBagConstraints.insets = new Insets(10, 10, 0, 10);
      gridBagConstraints.gridx = 1;
      nameLabel = new JLabel();
      nameLabel.setText(Messages.getString("ContainerElementPanel.0")); //$NON-NLS-1$
      jPanel = new JPanel();
      jPanel.setLayout(new GridBagLayout());
      jPanel.add(nameLabel, gridBagConstraints1);
      jPanel.add(getNameTextField(), gridBagConstraints);
      jPanel.add(getSubmitButton(), gridBagConstraints2);
      jPanel.add(getSymbolComboBox(), gridBagConstraints11);
    }
    return jPanel;
  }

  /**
   * This method initializes jScrollPane	
   * 	
   * @return javax.swing.JScrollPane	
   */
  private JScrollPane getJScrollPane() {
    if (jScrollPane == null) {
      jScrollPane = new JScrollPane();
      jScrollPane.setViewportView(getJTable());
    }
    return jScrollPane;
  }

  /**
   * This method initializes jTable	
   * 	
   * @return javax.swing.JTable	
   */
  private JTable getJTable() {
    if (jTable == null) {
      jTable = new BasicElementTable();
      jTable.setDefaultRenderer(JLabel.class, new JLabelTableRenderer());
      jTable.setRowHeight(22);
      jTable.addMouseListener(new ContainerTableMouseListener());
      jTable.getSelectionModel().addListSelectionListener(new ContainerTableSelectionListener());
      // password column renderer
      jTable.getColumn(jTable.getColumnName(2)).setCellRenderer(new PasswordTableCellRenderer(false));
    }
    return jTable;
  }
  
  /**
   * update
   *
   * @param containerElement
   */
  public void update(ContainerElement containerElement) {
    // save element
    this.containerElement = containerElement;
    // update values
    nameTextField.setText(containerElement.getName());
    symbolComboBox.setSelectedItem(containerElement.getSymbol());
    // set elements to model
    ((BasicElementTableModel)getJTable().getModel()).setBasicElements(containerElement.getElements());
  }

  /**
   * This method initializes nameTextField	
   * 	
   * @return javax.swing.JTextField	
   */
  private JTextField getNameTextField() {
    if (nameTextField == null) {
      nameTextField = new JTextField();
      nameTextField.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
      nameTextField.setPreferredSize(new Dimension(100, 19));
    }
    return nameTextField;
  }

  /**
   * This method initializes submitButton	
   * 	
   * @return javax.swing.JButton	
   */
  private JButton getSubmitButton() {
    if (submitButton == null) {
      submitButton = new JButton();
      submitButton.setText(Messages.getString("ContainerElementPanel.1")); //$NON-NLS-1$
      submitButton.setIcon(new ImageIcon(getClass().getResource("/org/javalobby/icons/20x20/DataStore.gif"))); //$NON-NLS-1$
      submitButton.addActionListener(new java.awt.event.ActionListener() {
        public void actionPerformed(java.awt.event.ActionEvent e) {
          saveFields();
        }
      });
    }
    return submitButton;
  }

  /**
   * saveFields
   *
   */
  private void saveFields() {
    // save values back to object
    if (!Utils.isEmpty(nameTextField.getText())) {
      containerElement.setName(nameTextField.getText());
      containerElement.setSymbol((String)symbolComboBox.getSelectedItem());
      JKeePass.application.setModified(true);
    }
    // refresh tree
    ElementTreePanel treePanel = JKeePass.application.getElementTreePanel();
    treePanel.treeNodeChanged((DefaultMutableTreeNode)treePanel.getLeadSelectionPath().getLastPathComponent());
  }
  
  /**
   * This method initializes symbolComboBox	
   * 	
   * @return javax.swing.JComboBox	
   */
  private JComboBox getSymbolComboBox() {
    if (symbolComboBox == null) {
      symbolComboBox = new SymbolComboBox();
    }
    return symbolComboBox;
  }

  /*
   * (non-Javadoc)
   * @see javax.swing.event.TreeSelectionListener#valueChanged(javax.swing.event.TreeSelectionEvent)
   */
  public void valueChanged(TreeSelectionEvent e) {
    // update fields
    TreePath treePath = e.getNewLeadSelectionPath();
    if (treePath != null) {
      // get node
      DefaultMutableTreeNode node = (DefaultMutableTreeNode) treePath.getLastPathComponent();
      if (node != null) {
        Element element = (Element)node.getUserObject();
        if (element instanceof ContainerElement) {
          // update values
          update((ContainerElement)element);
        } else {
          // TODO other panels?
        }
      }
    } else {
      // no selection
    }
    
  }

  /**
   * getContainerElement
   *
   * @return Returns the containerElement.
   */
  public void removeSelectedRow() {
    int row = jTable.getSelectedRow();
    if (row >= 0) {
      ((BasicElementTableModel)jTable.getModel()).removeRow(row);
    }
  }
  
  /**
   * getSelectedBasicElement
   *
   * @return
   */
  public BasicElement getSelectedBasicElement() {
    int row = jTable.getSelectedRow();
    if (row >= 0) {
      return ((BasicElementTableModel)jTable.getModel()).getBasicElement(row);
    }
    return null;
  }

  /**
   * This method initializes jPopupMenu	
   * 	
   * @return javax.swing.JPopupMenu	
   */
  private JPopupMenu getJPopupMenu() {
    if (jPopupMenu == null) {
      jPopupMenu = new JPopupMenu();
      jPopupMenu.add(editBasicElementAction);
      jPopupMenu.add(ActionManager.getDeleteBasicElementAction());
      jPopupMenu.add(ActionManager.getAddPasswordToClibboardAction());
    }
    return jPopupMenu;
  }

  /**
   * ContainerTableSelectionListener
   */
  private final class ContainerTableSelectionListener implements ListSelectionListener {
    public void valueChanged(ListSelectionEvent e) {
      int row = jTable.getSelectedRow();
      if (row >= 0) {
        // set element to local action
        BasicElement element = ((BasicElementTableModel)jTable.getModel()).getBasicElement(row);
        editBasicElementAction.setBasicElement(element);
        editBasicElementAction.setEnabled(true);
        ActionManager.getDeleteBasicElementAction().setEnabled(true);
        ActionManager.getAddPasswordToClibboardAction().setEnabled(true);
      } else {
        // reset element to local action
        editBasicElementAction.setBasicElement(null);
        editBasicElementAction.setEnabled(false);
        ActionManager.getDeleteBasicElementAction().setEnabled(false);
        ActionManager.getAddPasswordToClibboardAction().setEnabled(false);
      }
    }
  }

  /**
   * ContainerTableMouseListener
   */
  private final class ContainerTableMouseListener extends java.awt.event.MouseAdapter {
    public void mouseClicked(java.awt.event.MouseEvent e) {
      if (e.getClickCount() >= 2) {
        editBasicElementAction.actionPerformed(new ActionEvent(getJTable(),0,"edit")); //$NON-NLS-1$
      }
    }

    public void mousePressed(java.awt.event.MouseEvent e) {
      if (e.isPopupTrigger()) {
        selectNodeForLocation(e.getPoint());
        getJPopupMenu().show(e.getComponent(), e.getX(), e.getY());
      }
    }

    public void mouseReleased(java.awt.event.MouseEvent e) {
      if (e.isPopupTrigger()) {
        selectNodeForLocation(e.getPoint());
        getJPopupMenu().show(e.getComponent(), e.getX(), e.getY());
      }
    }

    private void selectNodeForLocation(Point point) {
      int row = jTable.rowAtPoint(point);
      if (row >= 0) {
        jTable.getSelectionModel().setLeadSelectionIndex(row);
      }
    }
  }
  
  /**
   * togglePasswordVisibility
   */
  public boolean togglePasswordVisibility() {
    boolean ret = false;
    TableCellRenderer renderer = jTable.getCellRenderer(0,2);
    if (renderer instanceof PasswordTableCellRenderer) {
      // toggle password
      ret = !(((PasswordTableCellRenderer)renderer).isShowPassword());
      ((PasswordTableCellRenderer)renderer).setShowPassword(ret);
      ((BasicElementTableModel)jTable.getModel()).fireTableDataChanged();
    }
    return ret;
  }
  
}
